/*
*************************************************
		Copyagent
	------------------------------------------
	            mining.c
*************************************************
Fisierul de data mining.
*/


#include <errno.h>
#include <stdio.h>
#include <netdb.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "mining_lib.h"
#include "baza_date_lib.h"
#include <mpi.h>

#define WITH_MPI

/*
prima iteratie - apar doar id-urile propozitiilor in care se regaseste cuvantul
+--------------------------------+
| id_prop1 |  id_prop2 | id_prop3|
+--------------------------------+

dupa a TUPLU_SIZE iteratie
+------------------+
| id_prop1 |  ...  |
+------------------+

apar doar id-urile propozitiilor care contin toate cele TUPLU_SIZE cuvinte

*/

int main(int argc, char * argv[])
{
	long ret = 0, prop_id = 0, nr_cuvinte = 0, nr_propozitii = 0, i = 0, j, k, l, m, n, p, tuplu_curent = 0, minim;
	int size = 0, my_rank = 0;
	/*Fiecare cuvant are un vector in care apar id-urile propozitiilor in care cuvantul se gaseste*/
	Vector * pointeri_vectori;
	Vector intersectie, intersectie1, intersectie2, cuvinte_ids, tuplu_cuvinte_id;;
 	char ** vector_cuvinte;
	
	
	ret = mysql_connection_start();
	
	if (ret != 0)
		return 0;
#ifdef WITH_MPI
		/* Inititalizarea MPI*/
	ret= MPI_Init(&argc, &argv);
	
	ret= MPI_Comm_size( MPI_COMM_WORLD, &size );
	
	ret= MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
#endif

	prop_id = ia_urmatoarea_propozitie(my_rank);
	while (prop_id != -1)
	{
	printf("Propozitia = %ld\n",prop_id);
	nr_cuvinte = nr_cuvinte_in_prop(prop_id);
	printf("Are %ld cuvinte\n", nr_cuvinte);
	if  (nr_cuvinte < TUPLU_SIZE) 
	{
		prop_id = ia_urmatoarea_propozitie(my_rank);
		tuplu_curent = 0;
		continue;
		//return 0;
	}
	
	vector_cuvinte = (char **)malloc(nr_cuvinte * sizeof(char *) );
	for ( i = 0 ; i < nr_cuvinte ; i++ )
		vector_cuvinte[i] = (char *)malloc(LUNG_MAX_CUV * sizeof(char));
	
	
	cuvinte_ids.vector = (long *)malloc(nr_cuvinte * sizeof(long));
	
	pune_cuvinte_prop_in_vector(prop_id, vector_cuvinte, cuvinte_ids);
	
/*	nr_vectori = Combinari(nr_cuvinte, TUPLU_SIZE);
	printf("C(%ld,%ld) = %ld\n", nr_cuvinte ,TUPLU_SIZE, Combinari(nr_cuvinte,TUPLU_SIZE));
	fflush(stdout);*/	
	pointeri_vectori = (Vector * )malloc(nr_cuvinte * sizeof (Vector));
	
	
	for ( i = 0 ; i < nr_cuvinte ; i++ )
	{
		nr_propozitii = nr_prop_cu_cuvantul(vector_cuvinte[i]);
		printf ("%ld aparitii ale lui %s\n", nr_propozitii, vector_cuvinte[i]);
		pointeri_vectori[i].vector = (long *)malloc(nr_propozitii * sizeof(long));
		pointeri_vectori[i].size = nr_propozitii;
		pune_prop_cu_cuvantul_in_vector(vector_cuvinte[i], pointeri_vectori[i]);
		
	}
	
	/*
	for ( i = 0 ; i < nr_cuvinte ; i++ )
	{
		printf("Propozitiile in care apare cuvintele %s", vector_cuvinte[i]);
		for ( j = 0 ; j < max_prop ; j++)
		{
			for (k = 0 ; k < nr_cuvinte ; k++)
			{
				
				
				if ( k == i)
					continue;
				{		
					
					if (j < pointeri_vectori[k].size)
					{
						
						printf("%ld - %ld \n", pointeri_vectori[i].vector[j] , pointeri_vectori[k].vector[j]);
						if (pointeri_vectori[i].vector[j] == pointeri_vectori[k].vector[j])
						{
							printf("si  %s \n",vector_cuvinte[k]);
							printf("%ld\n ", pointeri_vectori[i].vector[j]);
						}
					}
				}
			}
		}

	}

	
	*/	
	
	while ( tuplu_curent < TUPLU_SIZE)
	{	
	printf("Dim TUPLU: %ld\n", tuplu_curent+1);
	for ( i = 0 ; i < nr_cuvinte ; i++ )
	{
		//printf(" Intersectia vectorilor cuv: %s \n", vector_cuvinte[i]);
		//for ( p = 0 ; p < pointeri_vectori[i].size ; p++ )
		//	printf (" %ld: \n",pointeri_vectori[i].vector[p]);
		if (tuplu_curent>0)
		{	
			
			for ( j = i+1 ; j < nr_cuvinte ; j++ )
			{
				minim = mini(pointeri_vectori[i].size, pointeri_vectori[j].size);
				//printf("intersectie = %ld\n", minim);
				fflush(stdout);
				intersectie.vector = (long*)malloc(minim * sizeof(long));
				intersectie.size = intersectie_vectori(pointeri_vectori[i], pointeri_vectori[j], intersectie);
				
				tuplu_cuvinte_id.vector = (long *)malloc(2 * sizeof(long));
				tuplu_cuvinte_id.size = 2;
				tuplu_cuvinte_id.vector[0] = cuvinte_ids.vector[i];
				tuplu_cuvinte_id.vector[1] = cuvinte_ids.vector[j];
				

				salveaza_rezultatele_in_bd(intersectie, tuplu_cuvinte_id);
								
			/*	printf(" Intersectia vectorilor cuv: %s %s \n", vector_cuvinte[i], vector_cuvinte[j]);
			
				for ( p = 0 ; p < intersectie.size ; p++)
					printf("%ld\n",intersectie.vector[p]);
			*/
				if (tuplu_curent>1)
				{ 
					for ( k = j+1 ; k < nr_cuvinte ; k++ )
					{
						minim = mini(intersectie.size, pointeri_vectori[k].size);
						//printf("intersectie = %ld\n", minim);
						fflush(stdout);
						intersectie1.vector = (long*)malloc(minim * sizeof(long));
						intersectie1.size = intersectie_vectori(intersectie, pointeri_vectori[k], intersectie1);

						tuplu_cuvinte_id.vector = (long *)malloc(3 * sizeof(long));
						tuplu_cuvinte_id.size = 3;
						tuplu_cuvinte_id.vector[0] = cuvinte_ids.vector[i];
						tuplu_cuvinte_id.vector[1] = cuvinte_ids.vector[j];
						tuplu_cuvinte_id.vector[2] = cuvinte_ids.vector[k];
						
						salveaza_rezultatele_in_bd(intersectie1, tuplu_cuvinte_id);
								

				/*		printf(" Intersectia vectorilor cuv: %s %s %s  \n", vector_cuvinte[i], vector_cuvinte[j], vector_cuvinte[k]);
						for ( m = 0 ; m < intersectie1.size ; m++)
							printf("%ld\n",intersectie1.vector[m]);
				*/
						if (tuplu_curent>2)
						{
							
							for ( l = k+1 ; l < nr_cuvinte ; l++ )
							{
							
								minim = mini(intersectie1.size, pointeri_vectori[l].size);
				/*				printf("intersectie = %ld\n", minim);
								fflush(stdout);
				*/
								intersectie2.vector = (long*)malloc(minim * sizeof(long));
								intersectie2.size = intersectie_vectori(intersectie1, pointeri_vectori[l], intersectie2);
								
								tuplu_cuvinte_id.vector = (long *)malloc(4 * sizeof(long));
								tuplu_cuvinte_id.size = 4;
								tuplu_cuvinte_id.vector[0] = cuvinte_ids.vector[i];
								tuplu_cuvinte_id.vector[1] = cuvinte_ids.vector[j];
								tuplu_cuvinte_id.vector[2] = cuvinte_ids.vector[k];
								tuplu_cuvinte_id.vector[3] = cuvinte_ids.vector[l];

								salveaza_rezultatele_in_bd(intersectie2, tuplu_cuvinte_id);
				/*								
								printf(" Intersectia vectorilor cuv: %s %s %s %s \n", vector_cuvinte[i], vector_cuvinte[j], vector_cuvinte[k], vector_cuvinte[l]);
								for ( n = 0 ; n < intersectie2.size ; n++)
									printf("%ld\n",intersectie2.vector[n]);
				*/
							}
						}
						else
						{
						
						}
					}
				}
				else
				{
				
					
				}
				
			}
		}
		else
		{
			
			
	
		}				
	}
	tuplu_curent++;
	}
	tuplu_curent = 0;
	prop_id = ia_urmatoarea_propozitie(my_rank);
	}
#ifdef WITH_MPI
	MPI_Finalize();
#endif
	printf("GATA!\n");
	mysql_connection_end();
	
	
	return 0;
}

/*
int intersectie_vectori(int * vector1, int * vector2, int * vector_intersectie);
-------------------------------------------------
Face intersectia celor 2 vectori si intoarce cardinalul ei
-------------------------------------------------
self explainatory
*/
long intersectie_vectori(Vector vector1, Vector vector2, Vector vector_intersectie)
{
	long i, j, contor = 0;
	for( i = 0 ; i < vector1.size ; i++)
		for ( j = 0 ; j< vector2.size ; j++)
		{
				if (vector1.vector[i] == vector2.vector[j])
				{	
					if (contine(vector_intersectie.vector, contor, vector2.vector[j]) == 0 )
					{
						vector_intersectie.vector[contor] = vector2.vector[j];
						contor++;
					}
				}
		}
	printf("intersectia are %ld elemente\n", contor);
	vector_intersectie.size = contor;
	return contor;
	

}

